package com.zkzx.company.api.controller.sms;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.zkzx.common.exception.BaseException;
import com.zkzx.common.exception.ExceptionEnum;
import com.zkzx.common.global.Global;
import com.zkzx.common.sms.command.SmsCommand;
import com.zkzx.common.sms.constants.SmsTemplateEnum;
import com.zkzx.common.sms.constants.SmsTypeEnum;
import com.zkzx.common.sms.model.SmsVO;
import com.zkzx.company.api.client.company.CompanyClient;
import com.zkzx.company.api.service.authorization.MemberMapperService;
import com.zkzx.util.redis.CacheKeyUtil;
import com.zkzx.util.data.RandomStringGenerator;
import com.zkzx.util.redis.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


/**
 * @author young Email:yanghui@zkraising.com
 * @description
 * @company 北京中科智兴物联科技有限公司 @版权所有
 * @since 2021年05月18日 14时51分
 */
@RestController
@Slf4j
@Validated
@Api(tags="短信管理")
@RequestMapping(value = "/sms")
public class SmsController{

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private MemberMapperService memberMapperService;

    @NacosValue(value = "${captcha.debug}", autoRefreshed = true)
    private boolean captchaDebug;

    @Autowired
    private CompanyClient companyClient;


    // 万能验证码
    private final static String SMS_CODE = "021703";

    @PostMapping("/{type}")
    @ResponseStatus(HttpStatus.CREATED)
    @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码")
    public SmsVO sendSms(@PathVariable(value = "type") SmsTypeEnum type, @RequestBody SmsCommand command){

        // 根据type+手机号 生成缓存KEY
        String key = CacheKeyUtil.getCaptcha( type.name(), command.getPhone());
        // 先进行获取缓存数据 有直接抛出异常 操作太快 防止刷短信接口
        boolean keyBoolean = redisUtil.hasKey(key);
        if(keyBoolean){
            throw new BaseException(ExceptionEnum.VERIFICATION_CODE_FREQUENT_ERROR.getCode(),ExceptionEnum.VERIFICATION_CODE_FREQUENT_ERROR.getMsg());
        }

        // 基本校验
        check(type, command.getPhone());

        // 生成六位随机数
        String code = RandomStringGenerator.getRandomIntgerByLength(Global.SIX);
        // 测试环境 可以打开此开关 模拟发送短信
        if(captchaDebug){
            // 调试模式 启用万能验证码
            code = SMS_CODE;
        }
        log.info("{}发送短信验证码为：{}",type.getDescription(),code);

        Map<String, String> codeMap = new HashMap<>();
        codeMap.put(SmsTemplateEnum.SMS_CAPTCHA.getParameterArr()[Global.ZERO],code);
        //电话、模板编号、参数
        boolean sendBoolean = companyClient.sendSms(command.getPhone(), SmsTemplateEnum.SMS_CAPTCHA.getTemplate(), JSON.toJSONString(codeMap));
        if (!sendBoolean){
            throw new BaseException(ExceptionEnum.VERIFICATION_CODE_FAIL_ERROR.getCode(),ExceptionEnum.VERIFICATION_CODE_FAIL_ERROR.getMsg());
        }

        // 根据type设置的过期时间 生成缓存失效时间


        // 放入缓存
        redisUtil.set(key, SMS_CODE, type.getValue());

        // 验证码倒计时时间 返回前端
        return SmsVO.builder().interval(type.getValue()).build();
    }



    @PostMapping("/{type}/verification")
    @ResponseStatus(HttpStatus.CREATED)
    @ApiOperation(value = "校验短信验证码", notes = "校验短信验证码")
    public Boolean smsVerification(@PathVariable(value = "type") SmsTypeEnum type, @RequestBody SmsCommand command){

        // 根据type+手机号 生成缓存KEY
        String key = CacheKeyUtil.getCaptcha(type.name(), command.getPhone());
        // 根据KEY 获取缓存信息 进行匹配验证码是否正确，判断是否为null
        if (Objects.isNull(redisUtil.get(key))){
            throw new BaseException(ExceptionEnum.VERIFICATION_CODE_OVERDUE_ERROR.getCode(), ExceptionEnum.VERIFICATION_CODE_OVERDUE_ERROR.getMsg());
        }
        return command.getCode().equals(String.valueOf(redisUtil.get(key)));
    }


    /**
     * 基本校验
     * @param type 短信类型
     * @param mobile 手机号
     */
    private void check(SmsTypeEnum type, String mobile){

        // 修改登录密码 判断用户存不存在
        if(SmsTypeEnum.UPDATE_LOGIN_PASSWORD == type && Objects.isNull(memberMapperService.getByMobile(mobile))){
            throw new BaseException(ExceptionEnum.UPDATE_PASSWORD_CODE_ERROR.getCode(), ExceptionEnum.UPDATE_PASSWORD_CODE_ERROR.getMsg());
        }

    }




}
